<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */

namespace app\service\notice\feishu;

use app\enum\FsUrlEnum;
use app\enum\NoticeEnum;
use app\service\BaseService;
use app\service\notice\NoticeInterface;
use app\service\notice\NoticeLogTrait;
use proxy\Client;
use think\Exception;

/**
 * 飞书webhook服务
 */
class FeiShuWebHookService extends BaseService implements NoticeInterface
{
    use NoticeLogTrait;

    /**
     * @var array 请求参数
     */
    protected array $req = [];

    /**
     * @var array 应答参数
     */
    protected array $rep = [];

    /**
     * @var array 接收人
     */
    protected array $staffs = [];

    /**
     * @var int 通知类型
     */
    protected int $noticeType = NoticeEnum::NOTICE_TYPE_FS_WEBHOOK;

    /**
     * @var array 配置
     */
    private array $conf = [];

    public function __construct(array $conf = [])
    {
        $this->setConf($conf);
    }

    /**
     * 发送消息.
     * @param array $params 请求参数
     * @return bool
     * @throws Exception
     */
    public function sendSingleMessage(array $params = []): bool
    {
        $this->req = $this->getParam($params);
        $headers = $this->getHeader();
        $client = new Client();
        $serviceName = FsUrlEnum::getServiceName('feishu');
        $serviceUrl = $this->conf['link'] ?? '';
        if (! $serviceUrl) {
            return self::setError('未知webhook');
        }
        $this->rep = $client->postJson($serviceName, $serviceUrl, $this->req)->setHeader($headers)->exec(Client::RETURN_TYPE);
        if (! $this->setNoticeLog()) {
            return false;
        }
        return $this->isSendSuccess() || self::setError($res['msg'] ?? '发送失败');
    }

    /**
     * 群发消息.
     * @param array $params 请求参数
     * @return true
     */
    public function sendBatchMessage(array $params = []): bool
    {
        return true;
    }

    /**
     * 设置配置信息.
     * @param array $conf 配置
     */
    public function setConf(array $conf = []): bool
    {
        $this->conf = $conf;
        return true;
    }

    /**
     * 格式化参数.
     * @param array $params 配置
     */
    public function getParam(array $params = []): array
    {
        // 富文本发送
        return [
            'msg_type' => 'post',
            'content' => [
                'post' => [
                    'zh_cn' => [
                        'title' => $params['report_name'],
                        'content' => [
                            [
                                [
                                    'tag' => 'text',
                                    'text' => '报表：',
                                ],
                                [
                                    'tag' => 'a',
                                    'text' => '报表链接',
                                    'href' => $params['file_url'],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }

    /**
     * 是否发送成功.
     */
    public function isSendSuccess(): bool
    {
        return empty($this->rep['StatusCode']);
    }

    /**
     * 设置header.
     * @return string[]
     */
    private function getHeader(): array
    {
        return [
            'Content-Type' => 'application/json; charset=utf-8',
        ];
    }

    /**
     * 获取消息结构体.
     * @param array $params 请求参数
     */
    private function getBody(array $params = []): array
    {
        $body = [];
        $body['config']['wide_screen_mode'] = 1;
        $body['elements'][0]['tag'] = 'div';
        $body['elements'][0]['text'] = ['content' => ($params['msg'] ?? '未知内容'), 'tag' => 'lark_md'];
        $body['elements'][1]['tag'] = 'hr';
        $body['elements'][2]['tag'] = 'note';
        $body['elements'][2]['elements'][0] = ['content' => date('Y-m-d H:i:s') . ' 来自' . ($this->conf['bot_name'] ?? '机器人') . ']', 'tag' => 'lark_md'];
        $body['header']['template'] = 'red';
        $body['header']['title'] = ['content' => ($params['title'] ?? '预警'), 'tag' => 'plain_text'];

        return $body;
    }

    /**
     * 获取sign.
     * @param int $timestamp 时间戳
     */
    private function getSign(int $timestamp = 0): string
    {
        $hash = hash_hmac('sha256', '', $timestamp . "\n" . ($this->conf['sign'] ?? ''), true);
        return base64_encode($hash);
    }
}
